﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using FlashCards.Model;
using System.Data.Objects;
using System.Text;

namespace FlashCards.WebApp.Utils
{
    public class FlashcardUtils
    {
        static ObjectQuery<FlashcardSet> GetUserFlashcardSets(string userName, FlashCardsEntities context)
        {
            var list = context.FlashcardSets.Where(x => x.Creator.Nick == userName) as ObjectQuery<FlashcardSet>;

            return list;
        }

        public static List<FlashcardSet> GetUserFlashcardSets(string userName, bool includeFlashcards)
        {
            return GetUserFlashcardSets(userName, includeFlashcards, false);
        }

        public static List<FlashcardSet> GetUserFlashcardSets(string userName, bool includeFlashcards, bool includeGroup)
        {
            using (var context = new FlashCardsEntities())
            {
                var query = GetUserFlashcardSets(userName, context);

                if (includeFlashcards)
                    query = query.Include("Flashcards");

                if (includeGroup)
                    query = query.Include("Group");

                return query.ToList();
            }
        }

        static ObjectQuery<FlashcardSet> GetFlashcardSet(int flashcardSetId, FlashCardsEntities context)
        {
            return context.FlashcardSets.Where(x => x.FlashcardSetId == flashcardSetId) as ObjectQuery<FlashcardSet>;
        }

        public static FlashcardSet GetFlashcardSet(int flashcardSetId, bool includeFlashcards, bool includeGroup)
        {
            using (var context = new FlashCardsEntities())
            {
                var query = GetFlashcardSet(flashcardSetId, context);

                if (includeFlashcards)
                    query = query.Include("Flashcards");

                if (includeGroup)
                    query = query.Include("Group");

                return query.FirstOrDefault();
            }
        }

        public static List<FlashcardSet> GetPublicFlashcardSets()
        {
            using (var context = new FlashCardsEntities())
            {
                var list = new List<FlashcardSet>();

                list = context.FlashcardSets.Include("Flashcards").Where(x => x.IsPublic == true).ToList();

                return list;
            }
        }

        public static void DeleteFlashcardSet(int flashcardSetId, int userId)
        {
            using (var context = new FlashCardsEntities())
            {
                var flashcardSet = context.FlashcardSets.FirstOrDefault(x => x.FlashcardSetId == flashcardSetId);

                if (flashcardSet != null)
                {
                    if (flashcardSet.CreatorId != userId)
                    {
                        //TODO: raise exception
                    }

                    var repeats = context.Repeats.Where(x => x.FlashcardSetId == flashcardSetId).ToList();
                    foreach (var repeat in repeats)
                    {
                        //foreach (var repeatItem in repeat.RepeatItems)
                        //    context.RepeatItems.DeleteObject(repeatItem);
                        context.Repeats.DeleteObject(repeat);
                    }

                    context.FlashcardSets.DeleteObject(flashcardSet);
                    context.SaveChanges();
                }
            }
        }

        public static List<FlashcardSet> GetFlashcardSetsFromCategory(int categoryId)
        {
            using (var context = new FlashCardsEntities())
            {
                var category = context.Categories.Include("FlashcardSets.Flashcards").FirstOrDefault(x => x.CategoryId == categoryId);
                var categoryFlashcards = category.FlashcardSets.ToList();

                CategoriesUtils.GetInnerCategories(category);
                foreach (var innerCategory in category.ChildrenCategories)
                {
                    if (!innerCategory.FlashcardSets.IsLoaded)
                    {
                        innerCategory.FlashcardSets.Load();

                        foreach (var item in innerCategory.FlashcardSets)
                            if (!item.Flashcards.IsLoaded)
                                item.Flashcards.Load();
                    }

                    categoryFlashcards.AddRange(innerCategory.FlashcardSets);
                }

                return categoryFlashcards;
            }
        }

        public static List<FlashcardSet> GetPublicFlashcardSetsFromCategories(List<int> idList)
        {
            using (var context = new FlashCardsEntities())
            {
                var flashcards = context.FlashcardSets.Include("FLashcards")
                    .Where(x => idList.Contains(x.CategoryId) && x.IsPublic)
                    .ToList();
                return flashcards;
            }
        }

        public static List<NeuralNetworkResultSet> GetNetworkResult(int flashcardSetId, int userId)
        {
            using (var context = new FlashCardsEntities())
            {
                var resultSets = context.NeuralNetworkResultSets1
                    .Include("ai_NeuralNetworkResults")
                    .Where(x => x.UserID == userId)
                    .Where(x => x.FlashcardSetID == flashcardSetId)
                    .OrderByDescending(x => x.Date)
                    .Take(8)
                    .ToList();

                resultSets = resultSets.OrderBy(x => x.Date).ToList();

                return resultSets;
            }
        }

        public static Dictionary<int, string> GetFlashcardsTermsAsStrings(int flashcardSetId)
        {
            using (var context = new FlashCardsEntities())
            {
                var flashcardSet = context.FlashcardSets.FirstOrDefault(x => x.FlashcardSetId == flashcardSetId);
                var result = flashcardSet.Flashcards.ToDictionary(x => x.FlashcardId, x => Encoding.UTF8.GetString(x.Term.Data));

                return result;
            }
        }
    }
}